﻿using VideoTools.SubtitleEdit.Common;

namespace VideoTools.SubtitleEdit.SubtitleFormats
{
    public abstract class SubtitleFormat
    {
        public static bool SubtitleFormatsOrderChanged { get; set; }

        private static IList<SubtitleFormat> _allSubtitleFormats;
        private static IList<SubtitleFormat> _subtitleFormatsWithDefaultOrder;

        protected static readonly char[] SplitCharColon = { ':' };

        /// <summary>
        /// Text formats supported by Subtitle Edit
        /// </summary>
        public static IEnumerable<SubtitleFormat> AllSubtitleFormats
        {
            get
            {
                if (_allSubtitleFormats != null)
                {
                    if (SubtitleFormatsOrderChanged)
                    {
                        SubtitleFormatsOrderChanged = false;
                        _allSubtitleFormats = GetOrderedFormatsList(_subtitleFormatsWithDefaultOrder);
                    }

                    return _allSubtitleFormats;
                }

                _allSubtitleFormats = new List<SubtitleFormat>
                {
                    // new Idx(),
                };


                _subtitleFormatsWithDefaultOrder = new List<SubtitleFormat>(_allSubtitleFormats);
                _allSubtitleFormats = GetOrderedFormatsList(_subtitleFormatsWithDefaultOrder);

                return _allSubtitleFormats;
            }
        }

        protected int _errorCount;

        public abstract string Extension
        {
            get;
        }

        public abstract string Name
        {
            get;
        }

        public virtual bool IsMine(List<string> lines, string fileName)
        {
            var subtitle = new SubtitleEncode();
            var oldFrameRate = Configuration.CurrentFrameRate;
            LoadSubtitle(subtitle, lines, fileName);
            Configuration.CurrentFrameRate = oldFrameRate;
            return subtitle.Paragraphs.Count > _errorCount;
        }

        public abstract string ToText(SubtitleEncode subtitle, string title);

        public abstract void LoadSubtitle(SubtitleEncode subtitle, List<string> lines, string fileName);

        public virtual List<string> AlternateExtensions => new List<string>();

        public static double GetFrameForCalculation(double frameRate)
        {
            if (Math.Abs(frameRate - 23.976) < 0.001)
            {
                return 24000.0 / 1001.0;
            }
            if (Math.Abs(frameRate - 29.97) < 0.001)
            {
                return 30000.0 / 1001.0;
            }
            if (Math.Abs(frameRate - 59.94) < 0.001)
            {
                return 60000.0 / 1001.0;
            }

            return frameRate;
        }
        public static int MillisecondsToFramesMaxFrameRate(double milliseconds)
        {
            var frames = (int)Math.Round(milliseconds / (TimeCode.BaseUnit / GetFrameForCalculation(Configuration.CurrentFrameRate)), MidpointRounding.AwayFromZero);
            if (frames >= Configuration.CurrentFrameRate)
            {
                frames = (int)(Configuration.CurrentFrameRate - 0.01);
            }

            return frames;
        }

        public static int FramesToMillisecondsMax999(double frames)
        {
            var ms = (int)Math.Round(frames * (TimeCode.BaseUnit / GetFrameForCalculation(Configuration.CurrentFrameRate)), MidpointRounding.AwayFromZero);
            return Math.Min(ms, 999);
        }

        public bool BatchMode { get; set; }
        public double? BatchSourceFrameRate { get; set; }

        private static IList<SubtitleFormat> GetOrderedFormatsList(IEnumerable<SubtitleFormat> unorderedFormatsList)
        {
            IEnumerable<SubtitleFormat> newSelectedFormats = new[] { Utilities.GetSubtitleFormatByFriendlyName(Configuration.DefaultSubtitleFormat) };
            if (!string.IsNullOrEmpty(Configuration.FavoriteSubtitleFormats))
            {
                newSelectedFormats = newSelectedFormats.Union(Configuration.FavoriteSubtitleFormats.Split(';').Select(formatName => Utilities.GetSubtitleFormatByFriendlyName(formatName)));
            }

            return newSelectedFormats.Union(unorderedFormatsList).ToList();
        }
    }
}
